package com.xyht.sca_s.student_manage_system.common.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.SmsAttendance;
import com.xyht.sca_s.student_manage_system.modules.attendance.entity.SmsSchedulingTask;
import com.xyht.sca_s.student_manage_system.modules.attendance.mapper.SmsAttendanceMapper;
import com.xyht.sca_s.student_manage_system.modules.attendance.mapper.SmsSchedulingTaskMapper;
import com.xyht.sca_s.student_manage_system.modules.attendance.util.CheckOutlierUtil;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.websocket.entity.WebsocketResult;
import com.xyht.sca_s.student_manage_system.modules.websocket.myEnum.WebsocketResultEnum;
import com.xyht.sca_s.student_manage_system.modules.websocket.service.WebSocketService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

import static com.xyht.sca_s.student_manage_system.common.constant.CloseFlagConstant.IS_CLOSE_TRUE;
import static com.xyht.sca_s.student_manage_system.common.constant.SchedulingTaskTypeConstant.SCHEDULING_TASK_ATTENDANCE;

@Component
@Log4j2
public class DynamicSchedulingTaskUtil {
    // 注入ThreadPoolTaskScheduler对象
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    @Autowired
    private SmsSchedulingTaskMapper smsSchedulingTaskMapper;
    @Autowired
    private CheckOutlierUtil checkOutlierUtil;
    @Autowired
    private WebSocketService webSocketService;
    @Autowired
    private SmsAttendanceMapper smsAttendanceMapper;
    @Autowired
    private NewTipsUtil newTipsUtil;

    // 定义一个Map，用于存储定时任务的id和ScheduledFuture对象
    private Map<String, ScheduledFuture<?>> taskMap = new ConcurrentHashMap<>();

    // 定义一个方法，用于创建一个定时任务，并返回其id
    @Transactional
    public ResponseResult createTask(String name, String type, Date schedulingDate) {
        int threadCount = threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getActiveCount();
        int mapSize = taskMap.size();
//        if (mapSize == POOL_SIZE) {
//            return CommonResult.failed(CommonCodeEnum.SCHEDULING_THREAD_COUNT_LIMIT);
//        }
        ScheduledFuture scheduledFuture = taskMap.get(name);
        if (scheduledFuture != null) {
            return CommonResult.failed(CommonCodeEnum.SCHEDULING_NAME_EXIST);
        }

        SmsSchedulingTask task = smsSchedulingTaskMapper.selectOne(new QueryWrapper<SmsSchedulingTask>()
                .lambda()
                .eq(SmsSchedulingTask::getName, name));
        if (task != null && task.getId() != null){
            return CommonResult.failed(CommonCodeEnum.SCHEDULING_NAME_EXIST);
        }
        log.debug("这是定时任务测试,正在运行线程数：" + threadCount);
        log.debug("这是定时任务测试,Map中size大小：" + taskMap.size());
        //保存任务信息
        SmsSchedulingTask smsSchedulingTask = new SmsSchedulingTask();
        smsSchedulingTask.setName(name);
        smsSchedulingTask.setType(type);
        smsSchedulingTask.setExpirationTime(schedulingDate);
        smsSchedulingTaskMapper.insert(smsSchedulingTask);
        String smsSchedulingTaskID = smsSchedulingTask.getId();

        // 创建一个Runnable对象，表示要执行的任务内容
        Runnable runnable = () -> {
            log.debug("这是定时任务启动name"+name);
            if (SCHEDULING_TASK_ATTENDANCE.equals(type)) {
                log.debug("离散计算");
                checkOutlierUtil.checkOutlier(name);
                SmsAttendance smsAttendance = smsAttendanceMapper.selectById(name);
                if (smsAttendance != null){
                    //websocket实时更新
                    webSocketService.singleSend(smsAttendance.getAttendanceUserId(),
                            null,
                            WebsocketResult.success(WebsocketResultEnum.ATTENDANCE_STATUS_UPDATE));
                }
            }

            SmsSchedulingTask smsScheduling = new SmsSchedulingTask();
            smsScheduling.setId(smsSchedulingTaskID);
            smsScheduling.setIsClose(IS_CLOSE_TRUE);
            smsSchedulingTaskMapper.updateById(smsScheduling);
            taskMap.remove(name);

            //通知关闭
            newTipsUtil.cancelFinishTips(name);

            log.debug("这是定时任务结束");
        };
        // 创建一个CronTrigger对象，表示要执行的时间规则（这里使用cron表达式）
//        CronTrigger trigger = new CronTrigger(cron);
        // 调用schedule方法，传入Runnable对象和CronTrigger对象，创建一个ScheduledFuture对象表示定时任务（返回值是ScheduledFuture<?>类型）
        ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(runnable, schedulingDate);
        // 生成一个随机的id（这里简单使用UUID）
//        String id = UUID.randomUUID().toString();
        // 将id和future存入Map中
        taskMap.put(name, future);
        // 返回id
        return CommonResult.success();
    }

    // 定义一个方法，用于取消一个定时任务，并返回是否成功
    public ResponseResult cancelTask(String name) {
        SmsSchedulingTask task = smsSchedulingTaskMapper.selectOne(new QueryWrapper<SmsSchedulingTask>()
                .lambda()
                .eq(SmsSchedulingTask::getName, name));
        if (task == null || task.getId() == null){
            return CommonResult.failed(CommonCodeEnum.ATTENDANCE_NOT_EXIST);
        }

        SmsSchedulingTask smsScheduling = new SmsSchedulingTask();
        smsScheduling.setId(task.getId());
        smsScheduling.setIsClose(IS_CLOSE_TRUE);
        smsScheduling.setExpirationTime(new Date());
        smsSchedulingTaskMapper.updateById(smsScheduling);

//        if (SCHEDULING_TASK_ATTENDANCE.equals(task.getType())) {
//            log.debug("考勤打卡离散检测++++++++++++");
//            checkOutlierUtil.checkOutlier(name);
//        }
        // 从Map中根据id获取对应的future对象
        ScheduledFuture<?> future = taskMap.get(name);
        // 如果future不为空，则调用cancel方法取消该任务，并从Map中移除该键值对，并返回true；否则返回false。
        if (future != null) {
            log.debug("移除任务++++++++++++");
            future.cancel(true);
            taskMap.remove(name);
            return CommonResult.success();
        } else {
            return CommonResult.failed(CommonCodeEnum.SCHEDULING_THREAD_NOT_EXIST);
        }
    }

    // 定义一个方法，用于修改一个定时任务，并返回是否成功
//    public boolean updateTask(String name,Date schedulingDate) {
//        // 从Map中根据id获取对应的future对象
//        ScheduledFuture<?> future = taskMap.get(id);
//        // 如果future不为空，则先取消该任务，再重新创建一个新的任务，并替换原来的键值对，并返回true；否则返回false。
//        if (future != null) {
//            future.cancel(true);
//            createTask(cron);
//            taskMap.remove(id);
//            taskMap.put(id, taskMap.get(newId));
//            taskMap.remove(newId);
//            return true;
//        } else {
//            return false;
//        }
//    }


}
